package com.ifast.sys.service.impl;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.google.common.base.Objects;
import com.google.common.collect.Lists;
import com.ifast.common.base.CoreServiceImpl;
import com.ifast.common.domain.DictDO;
import com.ifast.common.domain.Tree;
import com.ifast.common.domain.TreeNode;
import com.ifast.common.service.DictService;
import com.ifast.common.utils.BuildTree;
import com.ifast.common.utils.BuildZTree;
import com.ifast.common.utils.Const;
import com.ifast.sys.dao.DeptDao;
import com.ifast.sys.domain.DeptDO;
import com.ifast.sys.service.DeptService;
import com.xiaoleilu.hutool.util.CollectionUtil;
import com.xiaoleilu.hutool.util.StrUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * <pre>
 * </pre>
 * <small> 2018年3月23日 | Aron</small>
 */
@Transactional
@Service
public class DeptServiceImpl extends CoreServiceImpl<DeptDao, DeptDO> implements DeptService {

    @Autowired
    private DictService dictService;

    @Value("${qylbid}")
    private String qylbid;

    @Override
    public Tree<DeptDO> getTree(String depId) {
        List<Tree<DeptDO>> trees = Lists.newArrayList();
        List<DeptDO> sysDepts;
        if(StrUtil.isNotBlank(depId)){
            DeptDO tiJ = new DeptDO();
            tiJ.setId(depId);
            sysDepts = this.listDeptTree(tiJ);
        }else{
            sysDepts = baseMapper.selectList(null);
        }
        for (DeptDO sysDept : sysDepts) {
            Tree<DeptDO> tree = new Tree<DeptDO>();
            tree.setId(sysDept.getId());
            tree.setParentId(sysDept.getParentId());
            tree.setText(sysDept.getName());
            Map<String, Object> state = new HashMap<>(16);
            state.put("opened", false);
            tree.setState(state);
            trees.add(tree);
        }
        // 默认顶级菜单为０，根据数据库实际情况调整
        if(Objects.equal(depId,"1")){
            depId = "0";
        }else{
            DeptDO deptDO = this.selectById(depId);
            depId = deptDO.getParentId();
        }
        return BuildTree.build(trees,depId);
    }

    @Override
    public boolean checkDeptHasUser(String deptId) {
        // 查询部门以及此部门的下级部门
        int result = baseMapper.getDeptUserNumber(deptId);
        return result == 0;
    }


    /**
     * 获取列表
     * @param page
     * @param deptDO
     * @return
     */
    @SuppressWarnings({ "unchecked", "rawtypes" })
	@Override
    public Page<DeptDO> listPage(Page page, DeptDO deptDO){
        return page.setRecords(baseMapper.listPage(page,deptDO));
    }

    @SuppressWarnings({ "unchecked", "rawtypes" })
	@Override
    public Page<DeptDO> listPageDwhy(Page page, DeptDO deptDO){
        return page.setRecords(baseMapper.listPageDwhy(page,deptDO));
    }

    public List<DeptDO> listDeptTree(DeptDO deptDO){
        return baseMapper.listDeptTree(deptDO);
    }

    @Override
    public List<DeptDO> listDeptUpTree(DeptDO deptDO){
        return baseMapper.listDeptUpTree(deptDO);
    }

    /**
     * 单位组织机构,不包含行业
     * @param depId
     * @return
     */
    @Override
	public List<TreeNode> getDeptByAuth(String depId){
		if(StringUtils.isBlank(depId)){
			return null;
		}
		DeptDO dept = this.selectById(depId);
        dept.setDwCodeLength(dept.getDwCode().length()+4);
		return BuildZTree.buildDept(this.baseMapper.listDeptNextByCodeT(dept));
	}

    /**
     * 单位组织机构,包含行业
     * @param depId
     * @return
     */
    @Override
	public List<TreeNode> getDeptHanyeByAuth(String depId){
		if(StringUtils.isBlank(depId)){
			return null;
		}
        List<DeptDO> deptDoListOne = Lists.newArrayList();
        DeptDO dept = this.selectById(depId);
        List<DictDO> dictDoList = dictService.selectList( new EntityWrapper<DictDO>().eq("PARENTID",qylbid).eq("DELFLAG", Const.DelEnum.no.getValue()).orderBy("sort", true));
        dept.setTypez(Const.DelState.del.getValue());
        dept.setHasChild(Const.DelState.del.getValue());
        deptDoListOne.add(dept);
        if(CollectionUtil.isNotEmpty(dictDoList)){
            for (DictDO dictDO : dictDoList) {
                DeptDO deptDONew = new DeptDO();
                deptDONew.setId(dictDO.getId());
                deptDONew.setName(dictDO.getName());
                deptDONew.setParentId(dept.getId());
                deptDONew.setHasChild(Const.DelState.del.getValue());
                deptDONew.setTypez(Const.DelState.del.getValue());
                List<DeptDO> deptDoListTwo = this.baseMapper.selectList(new EntityWrapper<DeptDO>().eq("length(DW_CODE)", 8).and().eq("QYLBID",dictDO.getId()));
                deptDoListTwo.forEach(deptDO ->{
                    deptDO.setParentId(dictDO.getId());
                    deptDO.setHasChild(Const.DelState.ndel.getValue());
                    deptDO.setTypez(Const.DelState.ndel.getValue());
                    deptDoListOne.add(deptDO);
                });
                deptDoListOne.add(deptDONew);
            }
        }
		return BuildZTree.buildDeptHanye(deptDoListOne);
	}

	@Override
	public List<TreeNode> getZTree(String depId) {
		List<TreeNode> trees = Lists.newArrayList();
        List<DeptDO> sysDepts = this.selectList(new EntityWrapper<DeptDO>().eq("PARENTID", StrUtil.isNotBlank(depId)?depId:0));
        for (DeptDO sysDept : sysDepts){  
            trees.add(TreeNode.builder().pId(sysDept.getParentId()).name(sysDept.getName()).id(sysDept.getId()).isParent(sysDept.getHasChild() == null ? true : sysDept.getHasChild() == 1).build());
        }
        return trees;
	}


    @Override
    public DeptDO selectMaxCodeByPid(DeptDO deptDO){
        return baseMapper.selectMaxCodeByPid(deptDO);
    }


    /**
     * 处理单位新增同时处理编码问题
     * @param deptDOC
     */
    private Lock lock = new ReentrantLock();

    @Override
    public void clInsertDept(DeptDO deptDOC) throws RuntimeException {
        lock.lock();//获取锁
        try {
            Wrapper<DeptDO> wrapper = new EntityWrapper<DeptDO>();
            wrapper.eq("id",deptDOC.getParentId());
            DeptDO  parentDeptDO = this.selectOne(wrapper);
            //本级最大code值
            DeptDO deptDOCode = this.selectMaxCodeByPid(deptDOC);
            if(deptDOCode == null){
                String dwCodep = parentDeptDO.getDwCode();
                deptDOC.setDwCode(dwCodep+"1000");
            }else{
                String hzCode = deptDOCode.getDwCode().substring(deptDOCode.getDwCode().length()-4,deptDOCode.getDwCode().length());
                String qzCode = deptDOCode.getDwCode().substring(0,deptDOCode.getDwCode().length()-4);
                deptDOC.setDwCode(qzCode+(Integer.valueOf(hzCode)+1)+"");
            }
            if(deptDOC.getDwCode().length() > 28){
                throw new Exception("单位级别大于7级");
            }
            //是否有下级
            Wrapper<DeptDO> wrapper1 = new EntityWrapper<DeptDO>();
            wrapper1.eq("parentId",deptDOC.getId());
            int countz = this.selectCount(wrapper1);
            if(countz > 0){
                deptDOC.setHasChild(1);
            }else{
                deptDOC.setHasChild(0);
            }
            this.insert(deptDOC);
            //跟新上级
            Wrapper<DeptDO> wrapper2 = new EntityWrapper<DeptDO>();
            wrapper2.eq("id",deptDOC.getParentId());
            DeptDO deptDoParent = this.selectOne(wrapper2);
            if(Objects.equal(Const.DelState.ndel.getValue(),deptDoParent.getHasChild())){
                deptDoParent.setHasChild(Const.DelState.del.getValue());
                this.updateById(deptDoParent);
            }
        }catch (Exception e) {
            throw new RuntimeException(e.toString(),e);
        }finally {
            lock.unlock(); //释放锁
        }
    }

    @Override
    public List<DeptDO> listDeptNextByCode(DeptDO deptDo){
        return baseMapper.listDeptNextByCode(deptDo);
    }


    @Override
    public void updateTree(){
       List<DeptDO> deptDoList = this.baseMapper.selectList(null);
        deptDoList.forEach(deptDO -> {
           //是否有下级
           Wrapper<DeptDO> wrapper1 = new EntityWrapper<DeptDO>();
           wrapper1.eq("parentId",deptDO.getId());
           int countz = this.selectCount(wrapper1);
           if(countz > 0){
               deptDO.setHasChild(1);
           }else{
               deptDO.setHasChild(0);
           }
       });
        this.updateBatchById(deptDoList);
    }

}
